#include "HyperTraceSymbolTable.h"

#include "Bridge.h"
#include "RichTextPainter.h"

class SymbolInfoWrapper {
  SYMBOLINFO info;

 public:
  SymbolInfoWrapper() { memset(&info, 0, sizeof(SYMBOLINFO)); }

  ~SymbolInfoWrapper() {
    if (info.freeDecorated) BridgeFree(info.decoratedSymbol);
    if (info.freeUndecorated) BridgeFree(info.undecoratedSymbol);
  }

  SYMBOLINFO* operator&() { return &info; }
  SYMBOLINFO* operator->() { return &info; }
};

HyperTraceSymbolTable::HyperTraceSymbolTable(QWidget* parent)
    : AbstractStdTable(parent), mMutex(QMutex::Recursive) {
  auto charwidth = getCharWidth();
  enableMultiSelection(true);
  setAddressColumn(0);
  addColumnAt(charwidth * 2 * sizeof(dsint) + 8, tr("Address"), true);
  addColumnAt(charwidth * 80, tr("Symbol"), true);
  loadColumnFromConfig("Symbol");

  Initialize();
}

QString HyperTraceSymbolTable::getCellContent(int r, int c) {
  QMutexLocker lock(&mMutex);
  if (!isValidIndex(r, c)) return QString();
  SymbolInfoWrapper info;
  DbgGetSymbolInfo(&mData.at(r), &info);
  switch (c) {
    case ColAddr:
      return ToPtrString(info->addr);
    case ColDecorated:
      return info->decoratedSymbol;
    default:
      return QString();
  }
}

bool HyperTraceSymbolTable::isValidIndex(int r, int c) {
  QMutexLocker lock(&mMutex);
  return r >= 0 && r < mData.size() && c >= 0 && c <= ColDecorated;
}

void HyperTraceSymbolTable::sortRows(int column, bool ascending) {
  QMutexLocker lock(&mMutex);
  std::stable_sort(
      mData.begin(), mData.end(),
      [column, ascending](const SYMBOLPTR& a, const SYMBOLPTR& b) {
        SymbolInfoWrapper ainfo, binfo;
        DbgGetSymbolInfo(&a, &ainfo);
        DbgGetSymbolInfo(&b, &binfo);
        switch (column) {
          case ColAddr:
            return ascending ? ainfo->addr < binfo->addr
                             : ainfo->addr > binfo->addr;
          case ColDecorated: {
            int result = strcmp(ainfo->decoratedSymbol, binfo->decoratedSymbol);
            return ascending ? result < 0 : result > 0;
          }
        }
      });
}
